package com.hulk.dryad.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.hulk.dryad.admin.api.vo.RoleMenuVO;
import com.hulk.dryad.admin.api.vo.SysRoleVO;
import com.hulk.dryad.admin.mapstruct.RoleMenuStruct;
import com.hulk.dryad.admin.mapstruct.SysRoleStruct;
import com.hulk.dryad.admin.service.SysRoleService;
import com.hulk.dryad.admin.service.SysUserRoleService;
import com.hulk.dryad.admin.service.SysUserService;
import com.hulk.dryad.common.annotation.Idempotent;
import com.hulk.dryad.common.annotation.OperLog;
import com.hulk.dryad.common.annotation.PrintlnLog;
import com.hulk.dryad.common.component.DryadUser;
import com.hulk.dryad.common.component.R;
import com.hulk.dryad.common.constant.enums.ActionType;
import com.hulk.dryad.common.constant.enums.BEC;
import com.hulk.dryad.common.util.SecurityUtils;
import com.hulk.dryad.persistence.entity.RoleMenuModel;
import com.hulk.dryad.persistence.entity.SysRoleModel;
import com.hulk.dryad.persistence.entity.SysUserModel;
import com.hulk.dryad.persistence.entity.SysUserRoleModel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author kim
 * @date 2020-02-10
 */
@ApiSort(5)
@Api(value = "role", tags = "角色管理模块")
@RestController
@RequiredArgsConstructor
@RequestMapping("/admin/role")
public class SysRoleController {

	private final SysRoleService sysRoleService;

	private final SysUserRoleService sysUserRoleService;

	private final SysUserService sysUserService;

	/**
	 * 通过ID查询角色信息
	 * @param id ID
	 * @return 角色信息
	 */
	@ApiOperation(value = "getById", notes = "通过ID查询角色信息")
	@PrintlnLog
	@GetMapping("/{id}")
	public R getById(@PathVariable Integer id) {
		SysRoleModel model = sysRoleService.getById(id);
		SysRoleVO vo = SysRoleStruct.INSTANCE.from(model);
		return R.ok(vo);
	}

	/**
	 * 验证角色名称是否存在
	 * @param roleName 角色名
	 * @return count
	 */
	@ApiOperation(value = "checkByName", notes = "验证角色名称是否存在")
	@PrintlnLog
	@GetMapping("/name/{roleName}")
	public R checkByName(@PathVariable String roleName) {
		int count = sysRoleService.count(Wrappers.<SysRoleModel>lambdaQuery().eq(SysRoleModel::getRoleName,roleName));
		if(count>0){
			return R.failed(BEC.E_1006,count);
		}
		return R.ok(count);
	}
	/**
	 * 验证角色编码是否存在
	 * @param roleCode 角色编码
	 * @return count
	 */
	@ApiOperation(value = "checkByCode", notes = "验证角色编码是否存在")
	@PrintlnLog
	@GetMapping("/code/{roleCode}")
	public R checkByCode(@PathVariable String roleCode) {
		int count = sysRoleService.count(Wrappers.<SysRoleModel>lambdaQuery().eq(SysRoleModel::getRoleCode,roleCode));
		if(count>0){
			return R.failed(BEC.E_1006,count);
		}
		return R.ok(count);
	}

	/**
	 * 添加角色
	 * @param vo 实体
	 * @return boolean
	 */
	@ApiOperation(value = "saveRole", notes = "添加角色")
	@Idempotent
	@OperLog(value ="添加角色",action = ActionType.ADD)
	@PostMapping
	@PreAuthorize("@pms.hasPermission('sys_role_add')")
	public R save(@Valid @RequestBody SysRoleVO vo) {
		SysRoleModel model = SysRoleStruct.INSTANCE.to(vo);
		boolean flag = sysRoleService.saveRole(model);
		return R.ok(flag);
	}

	/**
	 * 修改角色
	 * @param vo 实体
	 * @return boolean
	 */
	@ApiOperation(value = "updateRole", notes = "修改角色")
	@Idempotent
	@OperLog(value ="修改角色",action = ActionType.UPDATE)
	@PutMapping
	@PreAuthorize("@pms.hasPermission('sys_role_edit')")
	public R update(@Valid @RequestBody SysRoleVO vo) {
		SysRoleModel model = SysRoleStruct.INSTANCE.to(vo);
		boolean flag = sysRoleService.updateRoleById(model);
		return R.ok(flag);
	}

	/**
	 * 删除角色
	 * @param id ID
	 * @return
	 */
	@ApiOperation(value = "removeById", notes = "删除角色")
	@Idempotent
	@OperLog(value ="删除角色",action = ActionType.DEL)
	@DeleteMapping("/{id}")
	@PreAuthorize("@pms.hasPermission('sys_role_del')")
	public R removeById(@PathVariable Integer id) {
		boolean flag = sysRoleService.removeRoleById(id);
		return R.ok(flag);
	}

	/**
	 * 获取角色列表
	 * @return 角色列表
	 */
	@ApiOperation(value = "listRoles", notes = "获取角色列表")
	@PrintlnLog
	@GetMapping("/list")
	public R listRoles() {
		List<SysRoleModel> models = sysRoleService.list(Wrappers.emptyWrapper());
		List<SysRoleVO> vos =	SysRoleStruct.INSTANCE.from(models);
		return R.ok(vos);
	}

	@ApiOperation(value = "listScopeRole", notes = "获取用户角色列表")
	@PrintlnLog
	@GetMapping("/scopelist")
	public R listScopeRole() {
		Long userId = ((DryadUser) SecurityUtils.getUser()).getId();
		LambdaQueryWrapper<SysRoleModel> qw = Wrappers.lambdaQuery();

		SysUserModel user = sysUserService.getById(userId);
		if (!user.isRoot()) {
			List<Integer> userRoleIds = sysUserRoleService.list(
					Wrappers.<SysUserRoleModel>lambdaQuery().eq(SysUserRoleModel::getUserId, userId)
			).stream().map(SysUserRoleModel::getRoleId).collect(Collectors.toList());
			qw = Wrappers.<SysRoleModel>lambdaQuery()
					.in(SysRoleModel::getRoleId, userRoleIds);
		}
		List<SysRoleModel> models = sysRoleService.list(qw);
		List<SysRoleVO> vos = SysRoleStruct.INSTANCE.from(models);
		return R.ok(vos);
	}

	/**
	 * 分页查询角色信息
	 * @param page 分页对象
	 * @return 分页对象
	 */
	@ApiOperation(value = "getRolePage", notes = "分页查询角色信息")
	@PrintlnLog
	@GetMapping("/page")
	public R getRolePage(Page page) {
		Page<SysRoleModel> rpm = sysRoleService.page(page, Wrappers.emptyWrapper());
		Page<SysRoleVO> rpv = SysRoleStruct.INSTANCE.from(rpm);
		return R.ok(rpv);
	}

	/**
	 * 更新角色菜单
	 * @param role 角色对象
	 * @return boolean
	 */
	@ApiOperation(value = "saveRoleMenus", notes = "更新角色菜单")
	@Idempotent
	@OperLog(value ="更新角色菜单",action = ActionType.UPDATE)
	@PutMapping("/menu")
	@PreAuthorize("@pms.hasPermission('sys_role_perm')")
	public R saveRoleMenus(@RequestBody RoleMenuVO role) {
		RoleMenuModel model = RoleMenuStruct.INSTANCE.to(role);
		boolean flag = sysRoleService.updateRoleMenus(model);
		return R.ok(flag);
	}

	/**
	 * 通过角色ID 查询角色列表
	 * @param roleIdList 角色ID列表
	 * @return
	 */
	@ApiOperation(value = "getRoleList", notes = "通过角色ID 查询角色列表")
	@PrintlnLog
	@PostMapping("/getRoleList")
	public R getRoleList(@RequestBody List<Integer> roleIdList) {
		List<SysRoleModel> models = sysRoleService.findRolesByRoleIds(roleIdList, CollUtil.join(roleIdList, StrUtil.UNDERLINE));
		List<SysRoleVO> vos= SysRoleStruct.INSTANCE.from(models) ;
		return R.ok(vos);
	}

}
